home *** CD-ROM | disk | FTP | other *** search
/ Gold Medal Software 2 / Gold Medal Software Volume 2 (Gold Medal) (1994).iso / prog / asm_n_z.arj / SENDDISK.ASM < prev    next >
Assembly Source File  |  1988-11-08  |  17KB  |  541 lines

  1. ;********* S E N D D I S K . A S M *******************************************
  2. ; A disk duplication utility to allow all sectors (including boot)
  3. ; of a floppy disk to be transmitted via a temporary file over a
  4. ; modem and replaced on another floppy disk.  With this utility,
  5. ; you should be able to distribute the IBM PC-DOS 4.0 fix disks
  6. ; with the SBBS system.  The temporary file is 368,640 bytes long
  7. ; for a 360k diskette and twice that for a 720k diskette.  This is long,
  8. ; but length should compress nicely using pkarc or equivalent.
  9. ; The .exe version of this file needs to be included in the .ARC
  10. ; file distributed to enable recreation of the disk.
  11. ;
  12. ; This program will allow a BOOTABLE disk to be transmitted via a
  13. ; modem and recreated at another location.
  14. ;
  15. ; created 2 November 1988
  16. ;  Jim Offenbecher, Software Librarian, Huntsville PC Users Group
  17. ;   13920 Creely Drive SW
  18. ;    Huntsville, AL  35803
  19. ;     Tel: [H] (205) 882-3205
  20. ;          [W] (205) 881-5741
  21. ;
  22. ; modified to: 1.  Allow 720k disk usage with message showing type.
  23. ;              2.  Check file length prior to disk write.
  24. ;              3.  Comment the source code.
  25. ;      4 November 1988 - jko  (per conversation with IBM SBBS)
  26. ;
  27. ;  This program including source code is hereby placed in the
  28. ;  Public Domain for all to use.  This program including source
  29. ;  code may be freely distributed provided that no fee is charged
  30. ;  for it or it's distribution.  Feel free to modify it providing
  31. ;  original credits are retained - it is quick and dirty to allow
  32. ;  early distribution of the DOS 4.0 fixes...
  33. ;    yes I know the error exits don't reset the stack on exit...
  34. ; assemble with MASM 5.0 or above - no macros or libraries needed.
  35.  
  36. .model small
  37.  
  38. .data
  39. cr    equ    0dh
  40. lf    equ    0ah    
  41.  
  42. secsiz    equ    512
  43. sectrk    equ    9
  44. ;track count for 3.5" 720k disks
  45. trks7    equ    80
  46. ;track count for 5.25" 360k disks
  47. trks    equ    40
  48. sides    equ    2
  49. trklen    equ    secsiz * sectrk
  50.  
  51. ; number of clusters to check for when IDing the floppy
  52. ; if it's more than this, and the FAT ID is 0F9h, then it's a
  53. ; 5.25" 1.2 Meg and not a 720k 3.5" diskette...
  54.  
  55. clustchk    equ    750
  56.  
  57. signon    db    '            SENDDISK.EXE',cr,lf
  58.     db    cr,lf
  59.     db    'A Utility program to allow the IBM SBBS to',cr,lf
  60.     db    'distribute the patches for IBM Dos 4.0 via',cr,lf
  61.     db    'file mode.  This Program captures the entire',cr,lf
  62.     db    'disk into a single file and/or recreates the',cr,lf
  63.     db    'disk from the file.  It requires a disk which',cr,lf
  64.     db    'has been formatted to 360k (9 secs per track)',cr,lf
  65.     db    'or to 720k (80 tracks-9 secs per track- 3.5")',cr,lf
  66.     db    'in the A: or B: drive. It is quick and dirty,',cr,lf
  67.     db    'written in assembly, and is hereby placed in',cr,lf
  68.     db    'the public domain for all to use.',cr,lf
  69.     db    cr,lf
  70.     db    '           by Jim Offenbecher',cr,lf
  71.     db    '         SSS Computer Center Inc.',cr,lf
  72.     db    '           Huntsville, Alabama',cr,lf
  73.     db    'Software Librarian- Huntsville PC Users Group (P1239 AL)',cr,lf
  74.     db    cr,lf
  75. dirask    db    cr,lf,'Do you want to:',cr,lf
  76.     db    '      1.  Read a floppy disk into a file on hard disk',cr,lf
  77.     db    '      2.  Write a hard disk file onto a floppy disk',cr,lf
  78.     db    '  Enter your choice (1-2)->','$'
  79.  
  80. askerr    db    cr,lf,'Must be a 1 or 2 only',cr,lf,'$'
  81. as2err    db    cr,lf,'Must be an A or B only',cr,lf,'$'
  82.  
  83. askdsk    db    cr,lf,'Enter Floppy Disk Drive Designation (A-B)->','$'
  84.  
  85. typ360    db    cr,lf,'Diskette is 360k 5.25 inch',cr,lf,'$'
  86. typ720    db    cr,lf,'Diskette is 720k 3.5 inch',cr,lf,'$'
  87.  
  88. askfil    db    cr,lf,'Enter Hard Disk File Name ->','$'
  89.  
  90. rerr001    db    cr,lf,'Error Reading Floppy Disk',cr,lf,'$'
  91.  
  92. werr001    db    cr,lf,'Error Writing Floppy Disk',cr,lf,'$'
  93.  
  94. serr001    db    cr,lf,'File Size does NOT match disk type',cr,lf,'$'
  95.  
  96. newlin    db    cr,lf,'$'
  97.  
  98. nofile    db    cr,lf,'File Not Found',cr,lf,'$'
  99. badpath    db    cr,lf,'Invalid Path',cr,lf,'$'
  100. nohand    db    cr,lf,'No Handle Available',cr,lf,'$'
  101. accden    db    cr,lf,'Access to File Denied',cr,lf,'$'
  102. gopnerr    db    cr,lf,'Error Opening File',cr,lf,'$'
  103. gmaker    db    cr,lf,'Error Creating File',cr,lf,'$'
  104. rfiler    db    cr,lf,'Error Reading File',cr,lf,'$'
  105. wfiler    db    cr,lf,'Error Writing File',cr,lf,'$'
  106. closerr    db    cr,lf,'Error Closing File',cr,lf,'$'
  107.  
  108. fwtok    db    cr,lf,'Disk Capture Successful',cr,lf,'$'
  109. dwtok    db    cr,lf,'Disk Re-Creation Successful',cr,lf,'$'
  110.  
  111. dotmsg    db    '.$'
  112.  
  113. ; storage for temporary variables
  114.  
  115. ;file name input buffer
  116. bufinp    db    40    ;max length of buffer    
  117. chrcnt    db    0
  118. ;                1234567890123456789012345678901234567890
  119. filsto    db    '                                         '
  120.  
  121. ; ascii storage for the floppy drive involved
  122. drivasc db    'A'
  123.  
  124. ; binary storage for the floppy drive involved
  125. dskbin    db    1
  126.  
  127. ; disk type (number of tracks)
  128. dsktyp    dw    80
  129.  
  130. ;current sector storage for reading and writing floppy disk
  131. cursec    dw    0
  132.  
  133. ; storage for the file handle assigned to the temp file
  134. handle    dw    0
  135.  
  136. ; buffer for a single track of data...
  137. bugbuff    db    sectrk+1 dup (secsiz dup (?))
  138.  
  139. ; executable code begins here...
  140.  
  141. .code
  142.     mov    ax,@data    ;MASM 5.0+ find data segment
  143.     mov    ds,ax        ;set up data segment
  144.     mov    es,ax        ;set up extended segment too
  145. restart:
  146.     mov     dx,offset signon
  147.     mov    ah,9
  148.     int    21h        ;sign on the system
  149.     mov    ah,1
  150.     int    21h        ;get a single character
  151.     cmp    al,'1'        ;check for make file condition
  152.  
  153.     jz    makfil        ;go make a file if so
  154.     cmp    al,'2'        ;check for make disk condition
  155.     jz     makdsk        ;go make a disk if a 2
  156.     mov    dx,offset askerr
  157.     mov    ah,9        ;print error if not 1 or 2
  158.     int    21h
  159.     jmp    restart        ;and ask again
  160.  
  161. ;this module creates a file on the hard disk from all sectors on the
  162. ;specified floppy drive.  Drive type is checked to determine correct
  163. ;number of sectors to read.
  164.  
  165. makfil:
  166.     call    getdisk        ;find out which floppy to use
  167.     call    getfile        ;and the file name to use too
  168.     call    makefile    ; make the file
  169.     jc    exit        ;exit if error
  170.     mov    cx,0        ;start at sector zero
  171.     mov    cursec,cx
  172.     mov    cx,dsktyp    ;get # tracks this type
  173.  
  174. ; copy a single track from the floppy to a file, looping till all tracks done
  175. fillop:
  176.     push    cx        ;save track counter
  177.     mov    dx,offset dotmsg;tell user another track
  178.     mov    ah,9
  179.     int    21h
  180.     call    readdisk    ;go read track into buffer
  181.     call    writfile    ;write buffer out to file
  182.     mov    cx,cursec    ;get starting sector read last time
  183.     add    cx,9
  184.     mov    cursec,cx    ;bump the starting sector for next loop
  185.     pop    cx        ;get track counter back
  186.     dec    cx        ;one less track to do
  187.     jnz    fillop        ;loop till all tracks done...
  188.  
  189. ; all done writing the file, so bye-bye
  190.     call    closfile    ;close the new file
  191.     mov    dx,offset fwtok
  192.     jmp    errexit        ;tell user OK, and leave the program
  193.  
  194.  
  195. ; this module writes all sectors on a floppy disk from data in a
  196. ; file on the hard disk.  The floppy must be formatted, and the file
  197. ; length must match the format of the floppy disk.
  198.  
  199. makdsk:
  200.     call    getdisk        ;find out which floppy to use
  201.     call    getfile        ;and which file to write to it
  202.     call    openfile    ;open the file using handles
  203.     jc    exit        ;abort if can't open
  204.     call    lenchk        ;check length and abort if wrong
  205.     mov    cx,0        ;initialize the sector to write to
  206.     mov    cursec,cx
  207.     mov    cx,dsktyp    ;and get the track count from storage
  208.  
  209. ; this module reads one track's worth of data from the file and
  210. ; writes it out to the floppy, looping until 'dsktyp' tracks are written
  211.  
  212. fil2lop:
  213.     push    cx        ;save the track counter on stack
  214.     mov    dx,offset dotmsg    ;tell him we're working
  215.     mov    ah,9
  216.     int    21h
  217.     call    readfile    ;get one tracks data from file
  218.     call    writdisk    ;put it on the floppy
  219.     mov    cx,cursec    ;get the old starting sector written
  220.     add    cx,9        ;bump it one track's worth
  221.     mov    cursec,cx    ;and save it for next loop
  222.     pop    cx        ;get track counter back
  223.     dec    cx        ;one less track to do
  224.     jnz    fil2lop        ;loop till all tracks done...
  225. ;all done writing the floppy drive now...
  226.     call    closfile    ;close the file
  227.     mov    dx,offset dwtok
  228.     jmp    errexit        ;tell user OK, and exit the program
  229.  
  230. ;common exit point for errors... prints string at DS:DX and then exits...
  231. errexit:
  232.     mov    ah,9
  233.     int    21h
  234. exit:
  235.     mov    ah,4ch
  236.     int    21h
  237.  
  238. ; this module prompts the operator for the floppy drive to use, only A and
  239. ; B are acceptable answers.  It then checks the type of media involved using
  240. ; the FAT Descriptor for 360k drives, and a combination of the FAT Descriptor
  241. ; and the cluster count for 720k drives.  The correct number of 9 sectored
  242. ; tracks is stored for later loop usage.
  243.  
  244. getdisk:
  245.     mov    dx,offset askdsk
  246.     mov    ah,9
  247.     int    21h        ;ask the question
  248.     mov    ah,1
  249.     int    21h        ;get the answer
  250.     and    al,05fh        ;make lower case
  251.     cmp    al,3
  252.     jz    exit        ;exit on control-c
  253.     cmp    al,27
  254.     jz    exit        ;or on escape char
  255.     cmp    al,'A'        ;was it an 'A'???
  256.     jnz    gd002
  257. ;process drive A request
  258.     mov    drivasc,al    ;save for later use
  259.     sub    al,41h        ;convert to binary
  260.     mov    dskbin,al    ;save it too
  261.     jmp    gdret        ;jump around the B check and error for
  262.                 ;common return
  263. ;it wasn't an A so check for a B
  264. gd002:
  265.     cmp    al,'B'
  266.     jnz    gd003        ;not B either - then must be wrong
  267.     mov    drivasc,al    ;save the B for later use
  268.     sub    al,41h        ;convert to binary
  269.     mov    dskbin,al    ;save it too
  270.     jmp    gdret
  271.  
  272. ;here if not A or B - must be error...
  273. gd003:            ;here if in error
  274.     mov    dx,offset as2err
  275.     mov    ah,9
  276.     int    21h        ;tell him A or B only
  277.     jmp    getdisk        ;ask again...
  278.  
  279. ;here with al containing binary drive value...0=A, 1=B
  280. gdret:
  281.     inc    al        ;convert to base 1 for absolute call
  282.     mov    dl,al        ;put in DL for absolute call
  283.     mov    ah,1ch        ;put the GET FAT function in AH
  284.     push    ds        ;save from int 21 function
  285.     int    21h
  286.     jnc    gdret1        ;got a good fat description
  287.     jmp    readerr        ;couldn't get a good FAT description
  288.  
  289. ;here if got good fat function call - note:  DS has changed.....
  290. gdret1:
  291.     mov    al,Byte Ptr[bx]    ;get the Media Descriptor Byte...
  292.     pop    ds        ;restore Data Segment to ours...
  293.     cmp    al,0fdh        ;check for 9 sector 5.25 inch disk
  294.     jnz    chk720        ;no, check for the 720k...
  295.     mov    ax,80        ;360k disk has 40 trks, 2 sides, for tot of 80
  296.     mov    dsktyp,ax    ;save in storage for later loop
  297.     mov    dx,offset typ360
  298.     mov    ah,9
  299.     int    21h        ;tell user it's a 360
  300.     jmp    dskgood        ;go to common exit point...
  301.  
  302. ;here if wasn't a 360k drive in the selected drive...
  303. chk720:
  304.     cmp    al,0f9h        ;check for 3.5 inch disk...(maybe 1.2 Meg)??
  305.     jnz    readerr        ;if not 0fdh or 0f9h then must be wrong type
  306.  
  307. ; both the 3.5" 720k and the 1.2m 5.25 have an f9 Fat descriptor -
  308. ; use the tot clusters to insure it's a 720k...
  309.     cmp    dx,clustchk    ;check for 720k
  310.     jnc    readerr        ;error if it's too many
  311.     mov    ax,160        ;track count on 3.5 inch disk
  312.     mov    dsktyp,ax    ;save the total tracks for later looping use
  313.  
  314. ; now have good drive type entered, and know correct number of tracks to use
  315. dskgood:
  316.     mov    dx,offset newlin
  317.     mov    ah,9
  318.     int    21h        ;just start a new line for clarity...
  319.     ret
  320.  
  321.  
  322. ; this module prompts for and inputs a file name to use via the buffered
  323. ; input routine.  It also terminates the input with a zero byte for the
  324. ; file handle routines to come later...
  325.  
  326. getfile:
  327.     mov    dx,offset askfil
  328.     mov    ah,9
  329.     int    21h        ;show user what we want...
  330.     mov    ah,0ah        ;buffered input for file name...
  331.     mov    dx,offset bufinp
  332.     int    21h        ;get an input from him..
  333.     mov    al,chrcnt    ;get character count he entered
  334.     cmp    al,0        ;nothing means exit...
  335.     jnz    gfl01        ;he did something...
  336.     jmp    exit
  337. ;operator entered a response other than enter key...
  338. gfl01:
  339.     mov    ah,0        ;clear hi byte of AX
  340.     mov    di,offset filsto;set offset to 1st character entered
  341.     add    di,ax        ;add the number of chars entered
  342.     mov    byte ptr[di],0    ;put a zero terminator there
  343.     mov    dx,offset newlin;clear the line for clarity...
  344.     mov    ah,9
  345.     int    21h
  346.     ret
  347.  
  348. ; this module opens the file using the handle function...
  349. openfile:
  350.     mov    ah,3dh        ;function to open file handle
  351.     mov    al,0        ;read only mode - careful...
  352.     mov    dx,offset filsto;point to ASCIIZ name...
  353.     int    21h        ;go try to open...
  354.     jnc    openok        ;if carry not set, then ok...
  355.  
  356. ;here if error opening file... check sequentially for errors...
  357.     mov    dx,offset nofile
  358.     cmp    al,2        ;error 2 is no file found
  359.     jz    openerr
  360.     mov    dx,offset badpath
  361.     cmp    al,3        ;error 3 is can't find path
  362.     jz    openerr
  363.     mov    dx,offset nohand
  364.     cmp    al,4        ;error 4 is no handle available
  365.     jz    openerr
  366.     mov    dx,offset accden
  367.     cmp    al,5        ;error 5 is Access Denied
  368.     jz    openerr
  369.     mov    dx,offset gopnerr
  370.                 ;use general error if not above...
  371. openerr:
  372.     jmp    errexit        ;go print the error and quit...
  373.  
  374. ;here if file opened ok...
  375. openok:
  376.     mov    handle,ax    ;save handle for later use.
  377.     ret
  378.  
  379. ;tell operator we had an error reading file and then exit..
  380. readerr:
  381.     mov    dx,offset rerr001
  382.     jmp    errexit
  383.  
  384. ; this module creates a new file when reading in a floppy disk
  385. makefile:
  386.     mov    ah,3ch        ;function in AH
  387.     mov    cx,0        ;attributes set to none
  388.     mov    dx,offset filsto;point to ASCIIZ string inputted
  389.     int    21h        ;go try to make it
  390.     jnc    makeok        ;carry not set - then OK - it's made
  391.     mov    dx,offset badpath
  392.     cmp    al,3        ;error 3 is can't find path
  393.     jz    makerr
  394.     mov    dx,offset nohand
  395.     cmp    al,4        ;error 4 is no handle available
  396.     jz    makerr
  397.     mov    dx,offset accden
  398.     cmp    al,5        ;error 5 is access denied
  399.     jz    makerr
  400.     mov    dx,offset gmaker
  401.                 ;use general error if not above...
  402. makerr:
  403.     jmp    errexit        ;print the error for user and exit
  404.  
  405. ;here if file was created OK
  406. makeok:
  407.     mov    handle,ax    ;save handle for later writes...
  408.     ret
  409.  
  410. ;this module closes the file and updates the directory
  411. closfile:
  412.     mov    ah,3eh        ;function to close in AH
  413.     mov    bx,handle    ;get the saved handle
  414.     int    21h        ;go close it
  415.     jnc    closok        ;branch if no error ocurred
  416. ;here if error closing file
  417.     mov    dx,offset closerr
  418.     jmp    errexit        ;print the error and exit
  419. ;here if closed OK
  420. closok:
  421.     ret
  422.  
  423. ; this module reads one tracks worth of data (9 sectors) into the buffer.
  424. ; the file pointer is left for DOS to handle, we only do a sequential read.
  425.  
  426. readfile:
  427.     mov    ah,3fh        ;function in AH
  428.     mov    bx,handle    ;handle in BX
  429.     mov    dx,offset bugbuff;point to the buffer to use
  430.     mov    cx,trklen    ;number of bytes to read in CX
  431.     int    21h        ;go read the file
  432.     jnc    readok        ;skip error if none ocurred
  433. rfiler2:
  434.     mov    dx,offset rfiler
  435.     jmp    errexit        ;tell him an error and exit
  436.  
  437. ;here if no error ocurred, however, make sure we didn't run out of bytes...
  438. readok:
  439.     cmp    ax,cx        ;see if we read all we wanted...
  440.     jnz    rfiler2        ;error if short read...
  441.     ret
  442.  
  443. ; this routine writes one track's worth of data from the buffer to the file
  444. ; the file pointer is left for DOS to handle, we only do a sequential write.
  445. writfile:
  446.     mov    ah,40h        ;function in AH
  447.     mov    bx,handle    ;handle in BX
  448.     mov    dx,offset bugbuff;point to the buffer to use
  449.     mov    cx,trklen    ;number of bytes to write in CX
  450.     int    21h        ;go write it
  451.     jnc    writok        ;skip error if none ocurred
  452.  
  453. ;here if DOS reported an error
  454. wfiler2:
  455.     call    closfile        ;don't leave lost clusters
  456.     mov    dx,offset wfiler
  457.     jmp    errexit            ;tell user we can't write and exit
  458.  
  459. ;here if no error ocurred, however, make sure we wrote the whole buffer...
  460. writok:
  461.     cmp    ax,cx        ;check to see complete write
  462.     jnz    wfiler2        ;error if not
  463.     ret            ;else all is ok
  464.  
  465. ; this module reads one track's worth of data from the floppy disk
  466. readdisk:
  467.     mov    al,dskbin    ;get the disk to use
  468.     mov    cx,9        ;nine sectors per track
  469.     mov    dx,cursec    ;where to start
  470.     mov    bx,offset bugbuff;where to put data
  471.     int    25h        ;go do it
  472.     pop    cx        ;clean up stack from int 25h (the flags)
  473.     jnc    dredok        ;skip the error if ok
  474.     jmp    readerr        ;else tell user and exit
  475. ;here if read the track ok
  476. dredok:
  477.     ret
  478.  
  479. ; this module writes one track's worth of data to the floppy disk
  480. writdisk:
  481.     mov    al,dskbin    ;get the disk to use
  482.     mov    cx,9        ;write the whole nine sectors
  483.     mov    dx,cursec    ;where to start
  484.     mov    bx,offset bugbuff;where to get data from
  485.     int    26h        ;go do it
  486.     pop    cx        ;clean up stack from int 25h (the flags)
  487.     jnc    dwitok        ;skip the error if ok
  488.     jmp    writerr        ;else tell user and exit
  489. ;here if wrote the whole track
  490. dwitok:
  491.     ret
  492.  
  493. ;here if an error writing a track to floppy disk
  494. writerr:
  495.     mov    dx,offset werr001
  496.     jmp    errexit
  497.  
  498. ; check the length of the file to see if it came from the same type
  499. ; disk drive - 360k disks return DX=0005 and AX=A000 while
  500. ; 720k drives return DX=000B and AX=4000... error exit if no match..
  501.  
  502. lenchk:
  503.     mov    ax,4202h    ;LSEEK ref EOF
  504.     mov    bx,handle    ;file handle to use
  505.     mov    cx,0        ;cx and dx set the offset
  506.     mov    dx,cx        ;offset 0 from end
  507.     int    21h        ;go move the DOS pointer
  508.     push    dx        ;save the pointer (DX:AX) on stack for rewind
  509.     push    ax
  510.     mov    ax,4200h    ;LSEEK ref beginning
  511.     mov    bx,handle    ;same file
  512.     mov    cx,0        ;same offset
  513.     mov    dx,cx        ;offset 0 from beginning
  514.     int    21h        ;reset pointer to beginning
  515.     pop    ax        ;get the length back from the stack
  516.     pop    dx
  517. ; now have file length in DX:AX and pointer back at beginning of file...
  518.     mov    cx,dsktyp    ;get # tracks in CX
  519.     mov    si,5        ;set to 360k first
  520.     mov    di,0a000h
  521.     cmp    cx,80        ;check for 360k track count
  522.     jz    chkit        ;ok, then skip the set to 720k value
  523.     mov    si,0bh        ;set comparators to 720k standard
  524.     mov    di,04000h
  525. chkit:
  526. ; now compare DX with SI and AX with DI - if they dont both match, file
  527. ; is the wrong size...
  528.     cmp    dx,si        ;check hi words first
  529.     jnz    sizerr        ;error if not equal
  530.     cmp    ax,di        ;check lo words too
  531.     jnz    sizerr        ;error if not equal
  532.     ret            ;ok, file is right length
  533.  
  534. ; here if wrong size file - tell user and abort program.
  535. sizerr:
  536.     mov    dx,offset serr001
  537.     jmp    errexit
  538.  
  539. ;thats all folks......
  540. end
  541.